home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Sound / AHI / Developer / examples / Low-level / PTdatatype / LibCode.c < prev    next >
C/C++ Source or Header  |  1997-04-18  |  7KB  |  342 lines

  1. /*
  2. **  Q&D Protracker DataType
  3. **
  4. **      Written by Martin Blom, based on the AIFF DataType by
  5. **  Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  6. **  Public domain
  7. **
  8. */
  9.  
  10. #include "protracker.datatype_rev.h"
  11. #include "Data.h"
  12.  
  13.   // Mandatory library routines
  14.  
  15. struct ClassBase * LIBENT LibInit(REG(a0) BPTR LibSegment,REG(d0) struct ClassBase *ClassBase,REG(a6) struct ExecBase *ExecBase);
  16. struct ClassBase * LIBENT LibOpen(REG(a6) struct ClassBase *Base);
  17. BPTR LIBENT               LibExpunge(REG(a6) struct ClassBase *Base);
  18. BPTR LIBENT               LibClose(REG(a6) struct ClassBase *Base);
  19.  
  20.   // In RomTag.a
  21.  
  22. LONG                      LibNull(VOID);
  23.  
  24.   // The only user-callable routine
  25.  
  26. Class * LIBENT            GetClassEngine(REG(a6) struct ClassBase *ClassBase);
  27.  
  28.   // In Class.c
  29.  
  30. Object * LIBENT           ClassDispatch(REG(a0) Class *class,REG(a2) Object *object,REG(a1) Msg msg);
  31.  
  32.   // Vector initialization table
  33.  
  34. APTR LibVectors[] =
  35. {
  36.   LibOpen,
  37.   LibClose,
  38.   LibExpunge,
  39.   LibNull,
  40.  
  41.   GetClassEngine,
  42.  
  43.   (APTR)-1
  44. };
  45.  
  46.   // Library initialization table for MakeLibrary()
  47.  
  48. struct { ULONG DataSize; APTR Table; APTR Data; struct ClassBase * (*Init)(); } __aligned LibInitTab =
  49. {
  50.   sizeof(struct ClassBase),
  51.   LibVectors,
  52.   NULL,
  53.   LibInit
  54. };
  55.  
  56.   /* LibraryCleanup(struct ClassBase *ClassBase):
  57.    *
  58.    *  Closes all the libraries opened by LibrarySetup().
  59.    */
  60.  
  61. STATIC VOID
  62. LibraryCleanup(struct ClassBase *ClassBase)
  63. {
  64.   if(AHIDevice != -1)
  65.   {
  66.     CloseDevice((struct IORequest *) AHIio);
  67.     AHIDevice = -1;
  68.   }
  69.  
  70.   DeleteIORequest((struct IORequest *) AHIio);
  71.   AHIio = NULL;
  72.  
  73.   DeleteMsgPort(AHImp);
  74.   AHImp = NULL;
  75.  
  76.   CloseLibrary(SuperClassBase);
  77.   SuperClassBase = NULL;
  78.  
  79.   CloseLibrary(DataTypesBase);
  80.   DataTypesBase = NULL;
  81.  
  82.   CloseLibrary(UtilityBase);
  83.   UtilityBase = NULL;
  84.  
  85.   CloseLibrary(IntuitionBase);
  86.   IntuitionBase = NULL;
  87.  
  88.   CloseLibrary(DOSBase);
  89.   DOSBase = NULL;
  90. }
  91.  
  92.   /* LibrarySetup(struct ClassBase *ClassBase):
  93.    *
  94.    *  Sets up all the libraries this class requires to work.
  95.    */
  96.  
  97. STATIC BOOL
  98. LibrarySetup(struct ClassBase *ClassBase)
  99. {
  100.   if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",39))
  101.   {
  102.     if(IntuitionBase = OpenLibrary("intuition.library",39))
  103.     {
  104.       if(UtilityBase = OpenLibrary("utility.library",39))
  105.       {
  106.         if(DataTypesBase = OpenLibrary("datatypes.library",39))
  107.         {
  108.           if(SuperClassBase = OpenLibrary("datatypes/sound.datatype",39))
  109.           {
  110.             if(AHImp=CreateMsgPort())
  111.             {
  112.               if(AHIio=(struct AHIRequest *)CreateIORequest(
  113.                   AHImp,sizeof(struct AHIRequest)))
  114.               {
  115.                 AHIio->ahir_Version=2;
  116.                 if(!(AHIDevice=OpenDevice(AHINAME,AHI_NO_UNIT,
  117.                     (struct IORequest *) AHIio,NULL)))
  118.                 {
  119.  
  120.                   AHIBase = AHIio->ahir_Std.io_Device;
  121.                   return(TRUE);
  122.                 }
  123.               }
  124.             }
  125.           }
  126.         }
  127.       }
  128.     }
  129.   }
  130.  
  131.   LibraryCleanup(ClassBase);
  132.  
  133.   return(FALSE);
  134. }
  135.  
  136.   /* LibInit():
  137.    *
  138.    *  Initialize the library.
  139.    */
  140.  
  141. struct ClassBase * LIBENT
  142. LibInit(REG(a0) BPTR LibrarySegment,REG(d0) struct ClassBase *ClassBase,REG(a6) struct ExecBase *ExecBase)
  143. {
  144.     // Set up the header data; everything that doesn't get set
  145.     // up here will have been set up by InitResident().
  146.  
  147.   ClassBase->LibNode.lib_Revision = REVISION;
  148.  
  149.     // Remember the segment pointer
  150.  
  151.   Segment = LibrarySegment;
  152.  
  153.     // Remember the exec library base pointer
  154.  
  155.   SysBase = ExecBase;
  156.  
  157.     // Initialize the shared data access semaphore
  158.  
  159.   InitSemaphore(&LockSemaphore);
  160.  
  161.   return(ClassBase);
  162. }
  163.  
  164.   /* LibOpen(REG(a6) struct ClassBase *ClassBase):
  165.    *
  166.    *  Open the library, as called via OpenLibrary()
  167.    */
  168.  
  169. struct ClassBase * LIBENT
  170. LibOpen(REG(a6) struct ClassBase *ClassBase)
  171. {
  172.   struct SignalSemaphore *LocalSemaphore;
  173.  
  174.     // Prevent delayed expunge
  175.  
  176.   ClassBase->LibNode.lib_Flags &= ~LIBF_DELEXP;
  177.  
  178.     // We are going to modify data while in multitasking,
  179.     // so watch out
  180.  
  181.   ObtainSemaphore(LocalSemaphore = &LockSemaphore);
  182.  
  183.     // Is this the first initialization?
  184.  
  185.   if(++ClassBase->LibNode.lib_OpenCnt == 1)
  186.   {
  187.       // Open libraries & classes
  188.  
  189.     if(!LibrarySetup(ClassBase))
  190.       ClassBase = NULL;
  191.     else
  192.     {
  193.         // Create a new class
  194.  
  195.       if(!(SoundClass = MakeClass(ClassBase->LibNode.lib_Node.ln_Name,SOUNDDTCLASS,NULL,NULL,NULL)))
  196.       {
  197.         LibraryCleanup(ClassBase);
  198.         ClassBase = NULL;
  199.       }
  200.       else
  201.       {
  202.  
  203.           // Link the class dispatcher into it
  204.           // and keep a pointer to the library
  205.           // base
  206.  
  207.         SoundClass->cl_Dispatcher.h_Entry   = (HOOKFUNC)ClassDispatch;
  208.         SoundClass->cl_UserData             = (ULONG)ClassBase;
  209.  
  210.           // Make the class publicly available
  211.  
  212.         AddClass(SoundClass);
  213.       }
  214.     }
  215.   }
  216.  
  217.     // Release the lock
  218.  
  219.   ReleaseSemaphore(LocalSemaphore);
  220.  
  221.     // Return the library base, if any
  222.  
  223.   return(ClassBase);
  224. }
  225.  
  226.   /* LibExpunge(REG(a6) struct ClassBase *ClassBase):
  227.    *
  228.    *  Expunge the library, remove it from memory
  229.    */
  230.  
  231. BPTR LIBENT
  232. LibExpunge(REG(a6) struct ClassBase *ClassBase)
  233. {
  234.   BPTR LibrarySegment;
  235.  
  236.   LibrarySegment = NULL;
  237.  
  238.     // No more callers have the library open?
  239.  
  240.   if(ClassBase->LibNode.lib_OpenCnt == 0)
  241.   {
  242.       // Remember the segment pointer, so it can be unloaded
  243.  
  244.     LibrarySegment = Segment;
  245.  
  246.       // Remove the library from the public list
  247.  
  248.     Remove(ClassBase);
  249.  
  250.       // Free the vector table and the library data
  251.  
  252.     FreeMem((BYTE *)ClassBase - ClassBase->LibNode.lib_NegSize,ClassBase->LibNode.lib_NegSize + ClassBase->LibNode.lib_PosSize);
  253.   }
  254.   else
  255.   {
  256.       // Expunge it later
  257.  
  258.     ClassBase->LibNode.lib_Flags |= LIBF_DELEXP;
  259.   }
  260.  
  261.     // Return the segment pointer, if any
  262.  
  263.   return(LibrarySegment);
  264. }
  265.  
  266.   /* LibClose(REG(a6) struct ClassBase *ClassBase):
  267.    *
  268.    *  Close the library, as called by CloseLibrary()
  269.    */
  270.  
  271. BPTR LIBENT
  272. LibClose(REG(a6) struct ClassBase *ClassBase)
  273. {
  274.   BPTR LibrarySegment;
  275.  
  276.   LibrarySegment = NULL;
  277.  
  278.     // Decrement usage count
  279.  
  280.   if(ClassBase->LibNode.lib_OpenCnt > 0)
  281.   {
  282.       // No more users?
  283.  
  284.     if(--ClassBase->LibNode.lib_OpenCnt == 0)
  285.     {
  286.         // We are going to modify shared data,
  287.         // so watch out
  288.  
  289.       ObtainSemaphore(&LockSemaphore);
  290.  
  291.         // Clean up...
  292.  
  293.       if(SoundClass)
  294.       {
  295.         RemoveClass(SoundClass);
  296.         FreeClass(SoundClass);
  297.         SoundClass = NULL;
  298.       }
  299.  
  300.       LibraryCleanup(ClassBase);
  301.  
  302.         // Release the lock
  303.  
  304.       ReleaseSemaphore(&LockSemaphore);
  305.  
  306.         // Can we remove ourselves?
  307.  
  308.       if(ClassBase->LibNode.lib_Flags & LIBF_DELEXP)
  309.         LibrarySegment = LibExpunge(ClassBase);
  310.     }
  311.   }
  312.  
  313.   return(LibrarySegment);
  314. }
  315.  
  316.   /* GetClassEngine(REG(a6) struct ClassBase *ClassBase):
  317.    *
  318.    *  Get access to the class this library implements.
  319.    */
  320.  
  321. Class * LIBENT
  322. GetClassEngine(REG(a6) struct ClassBase *ClassBase)
  323. {
  324.   Class *class;
  325.  
  326.     // Access shared data
  327.  
  328.   ObtainSemaphoreShared(&LockSemaphore);
  329.  
  330.     // Remember the class pointer
  331.  
  332.   class = SoundClass;
  333.  
  334.     // Release the lock
  335.  
  336.   ReleaseSemaphore(&LockSemaphore);
  337.  
  338.     // Return the pointer
  339.  
  340.   return(class);
  341. }
  342.